package com.wugui.datax.admin.config;

import com.wugui.datax.admin.core.thread.JobTriggerPoolHelper;
import com.wugui.datax.admin.core.trigger.TriggerTypeEnum;
import com.wugui.datax.admin.dto.TriggerJobDto;
import com.wugui.datax.admin.entity.JobDatasource;
import com.wugui.datax.admin.entity.JobLog;
import com.wugui.datax.admin.mapper.JobLogMapper;
import com.wugui.datax.admin.service.JobDatasourceService;
import com.wugui.datax.admin.service.JobService;
import com.wugui.datax.admin.util.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @ClassName: DatabaseConnectionChecker
 * @Author: DKL
 * @CreateTime: 2024-01-04  14:18
 */
@Component
@Slf4j
public class DatabaseConnectionChecker implements ApplicationRunner {

    @Autowired
    private JobDatasourceService jobDatasourceService;
    @Resource
    private JobLogMapper jobLogMapper;

    private static boolean success = true; //连接是否都成功
    private static Date startTime; //开始时间
    private static Date endTime; //结束时间

    /**
     * @description: 长连接监测数据源连接情况
     * @author: dkl
     * @date: 2024/1/4 14:19
     **/
    @Override
    @Async
    public void run(ApplicationArguments args) {
        while (true) {
            try {
                List<JobDatasource> dataBaseInfoList = jobDatasourceService.selectAllDatasource();
                Thread.sleep(1000);
                Boolean test = test(dataBaseInfoList);
                if (test == false) {
                    //记录上次状态
                    success = false;
                }
                //比较这次和上次的结果
                if (test != success) {
                    endTime = new Date();
                    success = true;
                    log.info("开始时间:{}~结束时间:{}",startTime,endTime);
                    List<JobLog> errorLog = jobLogMapper.getAllByTime(startTime, endTime);
                    log.info("当前时间段是否有执行失败任务:{}",errorLog.size()>0?"是":"否");
                    if (errorLog.size()>0){
                        List<Integer> idList = errorLog.stream().map(JobLog::getJobId).collect(Collectors.toList());
                        List<Integer> ids = idList.stream().distinct().collect(Collectors.toList());
                        for (Integer id : ids) {
                            log.info("失败任务id:{}"+id);
                            TriggerJobDto dto = new TriggerJobDto();
                            dto.setJobId(id);
                            startJob(dto);
                            Thread.sleep(10000);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void startJob(TriggerJobDto dto) {
        String executorParam=dto.getExecutorParam();
        if (executorParam == null) {
            executorParam = "";
        }
        JobTriggerPoolHelper.trigger(dto.getJobId(), TriggerTypeEnum.MANUAL, -1, null, executorParam);
    }

    private Boolean test(List<JobDatasource> dataBaseInfoList) {
        int successNum = 0;
        for (JobDatasource dataBaseInfo : dataBaseInfoList) {
            try {
                String userName = AESUtil.decrypt(dataBaseInfo.getJdbcUsername());
                String pwd = AESUtil.decrypt(dataBaseInfo.getJdbcPassword());
                Connection conn = DriverManager.getConnection(dataBaseInfo.getJdbcUrl(), userName, pwd);
                if (conn != null) {
                    if (successNum == dataBaseInfoList.size()) {
                        successNum = 0;
                    } else {
                        successNum++;
                    }
                } else {
                    if (success == true) {
                        startTime = new Date();
                    }
                }
                conn.close();
            } catch (Exception e) {
                if (success == true) {
                    startTime = new Date();
                }
                return false;
            }
        }
        if (successNum == dataBaseInfoList.size()) {
            return true;
        } else {
            return false;
        }
    }
}
